package com.dengbw.systemtransfer.service;

import com.dengbw.systemtransfer.annotations.TimeSpeaker;
import com.dengbw.systemtransfer.global.Column;
import com.dengbw.systemtransfer.mapper.*;
import com.dengbw.systemtransfer.model.FuncId;
import com.dengbw.systemtransfer.model.db.*;
import com.dengbw.systemtransfer.model.exceptions.MyRuntimeException;
import com.dengbw.systemtransfer.model.function.CmmExtTask;
import com.dengbw.systemtransfer.model.function.Task;
import com.dengbw.systemtransfer.model.request.CunInfo;
import com.dengbw.systemtransfer.model.request.MultiTransfer;
import com.dengbw.systemtransfer.model.request.ZhenTransfer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author dengbw
 * @date 2021/11/2 2:48 下午
 */
@Slf4j
@Service
public class TransferService {
    MenuService menuService;
    SysUserService sysUserService;
    SysConfigService sysConfigService;
    CmmFunctionConfigService cmmFunctionConfigService;
    SysCorpVillageService sysCorpVillageService;
    PstFarmerService pstFarmerService;
    CmmFunctionExtConfigService cmmFunctionExtConfigService;
    DingCommonService dingCommonService;
    AdminAreaService adminAreaService;
    UpdateService updateService;
    CmmFunctionExtConfigMapper cmmFunctionExtConfigMapper;
    CmmFunctionCofigMapper cmmFunctionCofigMapper;
    SysConfigMapper sysConfigMapper;
    SysMenuMapper sysMenuMapper;
    SysRoleMapper sysRoleMapper;
    SysRoleMenuMapper sysRoleMenuMapper;
    SysOrgMapper sysOrgMapper;
    SysCorpMapper sysCorpMapper;
    SysCorpVillageMapper sysCorpVillageMapper;
    SysRoleService sysRoleService;
    SysCorpStationService sysCorpStationService;

    @Autowired
    public TransferService(MenuService menuService, SysUserService sysUserService, SysConfigService sysConfigService, CmmFunctionConfigService cmmFunctionConfigService, SysCorpVillageService sysCorpVillageService, PstFarmerService pstFarmerService, CmmFunctionExtConfigService cmmFunctionExtConfigService, DingCommonService dingCommonService, AdminAreaService adminAreaService, UpdateService updateService, CmmFunctionExtConfigMapper cmmFunctionExtConfigMapper, CmmFunctionCofigMapper cmmFunctionCofigMapper, SysConfigMapper sysConfigMapper, SysMenuMapper sysMenuMapper, SysRoleMapper sysRoleMapper, SysRoleMenuMapper sysRoleMenuMapper, SysOrgMapper sysOrgMapper, SysCorpMapper sysCorpMapper, SysCorpVillageMapper sysCorpVillageMapper, SysRoleService sysRoleService, SysCorpStationService sysCorpStationService) {
        this.menuService = menuService;
        this.sysUserService = sysUserService;
        this.sysConfigService = sysConfigService;
        this.cmmFunctionConfigService = cmmFunctionConfigService;
        this.sysCorpVillageService = sysCorpVillageService;
        this.pstFarmerService = pstFarmerService;
        this.cmmFunctionExtConfigService = cmmFunctionExtConfigService;
        this.dingCommonService = dingCommonService;
        this.adminAreaService = adminAreaService;
        this.updateService = updateService;
        this.cmmFunctionExtConfigMapper = cmmFunctionExtConfigMapper;
        this.cmmFunctionCofigMapper = cmmFunctionCofigMapper;
        this.sysConfigMapper = sysConfigMapper;
        this.sysMenuMapper = sysMenuMapper;
        this.sysRoleMapper = sysRoleMapper;
        this.sysRoleMenuMapper = sysRoleMenuMapper;
        this.sysOrgMapper = sysOrgMapper;
        this.sysCorpMapper = sysCorpMapper;
        this.sysCorpVillageMapper = sysCorpVillageMapper;
        this.sysRoleService = sysRoleService;
        this.sysCorpStationService = sysCorpStationService;
    }

    @TimeSpeaker("transfer multi village")
    public Map<String, String> transferBatch(MultiTransfer multi) {
        if (CollectionUtils.isEmpty(multi.getZhenTransferList())) {
            return new HashMap<>();
        }
        Map<String, String> result = new HashMap<>();
        multi.getZhenTransferList().forEach(v -> v.getCunInfoList().forEach(c -> {
            transferSingle(v, c);
            result.put(c.getCorpId(), c.getCorpId() + " -> " + v.getZhenCorpId() + "." + c.getSubIdInZhen());
        }));
        return result;
    }

    @TimeSpeaker("transfer single village")
    public void transferSingle(ZhenTransfer zhen, CunInfo cunInfo) {
        deleteOld(cunInfo.getCorpId());
        updateService.updateDeployed(zhen, cunInfo);
        sysRoleService.saveRole(zhen.getZhenCorpId(), cunInfo.getSubIdInZhen());
        if (notExistInZhen(cunInfo.getSubIdInZhen(), zhen.getZhenCorpId())) {
            insertNew(zhen, cunInfo);
        }
        fixAfterTransfer(zhen, cunInfo);
        log.info(cunInfo.getCorpId() + " moved to " + zhen.getZhenCorpId() + "." + cunInfo.getSubIdInZhen());
    }

    @TimeSpeaker("delete old")
    public void deleteOld(String cunCorpId) {
        cmmFunctionExtConfigMapper.delete(v -> v.eq(Column.TENANT_ID, cunCorpId));
        cmmFunctionCofigMapper.delete(v -> v.eq(Column.TENANT_ID, cunCorpId));
        sysCorpVillageMapper.delete(v -> v.eq(Column.TENANT_ID, cunCorpId));
        sysConfigMapper.delete(v -> v.eq(Column.TENANT_ID, cunCorpId));
        sysMenuMapper.delete(v -> v.eq(Column.TENANT_ID, cunCorpId));
        sysRoleMapper.delete(v -> v.eq(Column.TENANT_ID, cunCorpId));
        sysRoleMenuMapper.delete(v -> v.eq(Column.TENANT_ID, cunCorpId));
        sysOrgMapper.delete(v -> v.eq(Column.TENANT_ID, cunCorpId));
        sysCorpMapper.delete(v -> v.eq(Column.DING_CORP_ID, cunCorpId));
    }

    public boolean notExistInZhen(Long cunSubId, String zhenCorpId) {
        List<SysCorpVillage> villages = sysCorpVillageMapper.queryList(v -> v.eq(Column.TENANT_ID, zhenCorpId).eq(Column.SUB_ID, cunSubId));
        return CollectionUtils.isEmpty(villages);
    }

    @TimeSpeaker("insert new")
    public void insertNew(ZhenTransfer zhen, CunInfo cunInfo) {
        Map<String, String> core = dingCommonService.fetchCore(zhen.getAppKey(), zhen.getAppSecret());
        save(zhen, cunInfo, core);
    }

    public void save(ZhenTransfer zhenTransfer, CunInfo cunInfo, Map<String, String> core) {
        String zhenCorpId = zhenTransfer.getZhenCorpId();
        sysCorpVillageService.saveSysCorpVillage(zhenTransfer, cunInfo);
        cmmFunctionExtConfigService.saveExtConfig(zhenCorpId, cunInfo.getSubIdInZhen(), core);
        cmmFunctionConfigService.saveFunctionConfig(zhenCorpId, cunInfo.getSubIdInZhen(), core);
        sysConfigService.saveSysConfig(zhenCorpId, cunInfo);
        sysRoleService.saveRole(zhenCorpId, cunInfo.getSubIdInZhen());
        sysUserService.saveUserRole(zhenCorpId, cunInfo.getSubIdInZhen(), cunInfo.getCorpId());
        menuService.saveMenu(zhenCorpId, cunInfo.getSubIdInZhen());
        sysCorpStationService.saveSysCorpStation(zhenCorpId, cunInfo.getSubIdInZhen(), cunInfo.getZhudiwangId(), cunInfo.getZhudiwangBianhao());
    }

    public void enableSync(String zhenCorpId) {
        List<SysCorp> corps = sysCorpMapper.queryList(v -> v.eq(Column.TENANT_ID, zhenCorpId));
        corps.forEach(c -> {
            c.setNeedSync(1);
            sysCorpMapper.updateById(c);
        });
    }

    @TimeSpeaker("fix after transfer")
    public void fixAfterTransfer(ZhenTransfer zhen, CunInfo cunInfo) {
        sysUserService.updateUser(cunInfo.getSubIdInZhen());
        enableSync(zhen.getZhenCorpId());
        List<Long> subids = new ArrayList<>(1);
        subids.add(cunInfo.getSubIdInZhen());
        sysUserService.updateUser(subids);
        pstFarmerService.addToFarmer(zhen.getZhenCorpId(), cunInfo.getSubIdInZhen());
        sysUserService.fixMenu(zhen.getZhenCorpId());
    }
}
